import { useRef, useState } from 'react'

import { useToast } from 'v1-components'
import { useAtom } from 'jotai'
import type { ISearchInput } from '../../../shared/types'
import { trpc } from '@/trpc'
import { answerAtom } from '@/store/question'

export function autoCloseTag(code: string) {
  const stack: string[] = []
  const lines = code.split('\n')
  let needRender = true
  const result = lines.map((line) => {
    // iterate through the line to complete the jsx
    for (let i = 0; i < line.length; i++) {
      const char = line[i]

      if (char === '<') {
        const nextChar = line[i + 1]

        if (nextChar === '/') {
          // find the '>'
          const endIndex = line.slice(i + 1).indexOf('>')
          if (endIndex !== -1)
            stack.pop()
          else
            return line.slice(0, i) + stack.pop()
        }
        else {
          const tagName = line.slice(i + 1).match(/^[a-zA-Z0-9]+/)?.[0]
          if (tagName)
            stack.push(`</${tagName}>`)
        }
      }

      if (char === '/' && line[i + 1] === '>')
        stack.pop()
    }
    if (line.includes('render('))
      needRender = false

    return line
  })
  if (stack.length) {
    result[result.length - 1] += `\n${stack.map((tag, idx) => {
      let result = `    ${tag}`
      let i = 0
      while (i < idx) {
        result = `  ${result}`
        i++
      }

      return result
    }).reverse().join('\n')}\n  )\n}`
  }
  if (needRender) {
    const name = getFCName(code)
    if (name)
      result.push(`render(<${name} />, document.getElementById('app'))`)
  }
  return result.join('\n')
}

function getFCName(jsxCode: string) {
  const regex = /(?<=function\s+)[A-Z]\w*(?=\s*\()/g
  return jsxCode.match(regex)?.[0]
}

function getId(str: string) {
  const regex = /id: (.+)/
  const match = str.match(regex)

  if (match && match[1])
    return match[1]

  return null
}

export function useGenCode(question: ISearchInput) {
  const [completedCode, setCompletedCode] = useState('')
  const codeRef = useRef('')
  const { toast } = useToast()
  const idRef = useRef<string | null>(null)
  const [, setAnswers] = useAtom(answerAtom)
  trpc.codeGen.useSubscription(question, {
    onData: (trunk) => {
      // first line is the id, like `id: ${id}`, TODO: replace with isolated trpc call
      if (trunk && idRef.current === null) {
        idRef.current = getId(trunk) || 'UNKWON'
        setAnswers(prev => [...prev, idRef.current!])
      }
      else {
        setCompletedCode(() => {
          codeRef.current += trunk
          return autoCloseTag(codeRef.current)
        })
      }
    },
    onError(error) {
      toast({
        title: 'Uh oh! Something went wrong.',
        description: error.message,
      })
      console.error(error)
    },
  })
  return [completedCode, setCompletedCode] as const
}
